package com.chatTools.protocol;

import com.chatTools.config.Config;
import com.chatTools.message.ChatResponseMessage;
import com.chatTools.message.GroupChatResponseMessage;
import com.chatTools.message.GroupCreateResponseMessage;
import com.chatTools.message.Message;
import com.google.gson.*;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.lang.reflect.Type;
import java.util.List;

/**
 * @author： pang-yun
 * @date： 2021-09-16 15:28
 * 功能目的 ：用于   ByteToMessageCodec 默认不能共享
 * 要解决这个问题需要使用新的父类   MessageToMessageCodec<a,b>  此类默认你得到的是 完整的消息  因此可以共享   a 输入类类型  b 输出类类型
 */


// 注意： 此类必须和 LengthFieldBasedFrameDecoder  来使用 确保此类 使用时 得到的消息全部完整
@Slf4j
@ChannelHandler.Sharable   //表名此类可以共享使用
public class MessageCodecSharable extends MessageToMessageCodec<ByteBuf, Message> {
    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> outList) throws Exception {
        ByteBuf out = ctx.alloc().buffer();
        // 1. 魔数  4 字节   判断是否为有效数据包
        out.writeBytes(new byte[]{1, 2, 3, 4});
        // 2. 版本号  1 字节 的版本
        out.writeByte(1);
        //3. 用一个字节 代表 序列化 算法  JDK 0   json 1
        //out.writeByte(0);
        out.writeByte(Config.getSerializerAlgorithm().ordinal());
        //4. 从 msg 中取出 指令类型  一个字节
        out.writeByte(msg.getMessageType());

        // 5. 请求序号  4 个字节
        out.writeInt(msg.getSequenceId());

        // ----添加一个 无意义字节  对齐填充 满足 二的整数倍
        out.writeByte(0xff);

        // 6. 获取内容的字节数组   通过
      /*  ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(msg);
        byte[] bytes = bos.toByteArray();*/
        byte[] bytes = Config.getSerializerAlgorithm().serializer(msg);

        // 7. 长度  4个字节
        out.writeInt(bytes.length);

        // 8. 内容
        out.writeBytes(bytes);

        outList.add(out);


    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // 获取魔数
        int magicNum = in.readInt();
        //  获取版本
        byte version = in.readByte();
        // 获取序列化方式
        byte serializerType = in.readByte();
        // 获取指令类型
        byte messageType = in.readByte();
        // 获取消息序号
        int sequenceId = in.readInt();
        // 获取 无意义 字节
        byte b = in.readByte();
        // 获取长度
        int length = in.readInt();
        // 分配 内容长度的数组  准备读取内容
        byte[] bytes = new byte[length];

        // 读取 消息内容的长度
        in.readBytes(bytes, 0, length);

        Message message = null;
        // 如果序列化类型是 jdk
        // 开始反序列化   ObjectInputStream  反序列化流
      /*  ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
        message = (Message) ois.readObject();
*/

        /**
         * - 首先确定反序列化类型  确定具体的消息 然后才能实现反序列化
         * */
        Serializer.Algorithm serializer = Serializer.Algorithm.values()[serializerType];
        Class<?> aClass = Message.getMessageClass(messageType);
        Object o = serializer.deserializer(aClass, bytes);

        //----------将解析出的结果打印
        log.info(" 返回消息------>>>>>>>  {}, {}, {}, {}, {}, {}", magicNum, version, serializerType, messageType, sequenceId, length);
        log.info("{}", message);

        // 将解析的结果放入 list中  准备给下一个 handler 使用
       // out.add(message);
        out.add(o);
        if (message instanceof ChatResponseMessage) {
            ChatResponseMessage msg = (ChatResponseMessage) message;
            System.out.println("----------------------");
            System.out.println("新消息 : " + msg.getContent());
            System.out.println("----------------------");

        }

        if (message instanceof GroupCreateResponseMessage) {
            GroupCreateResponseMessage msg = (GroupCreateResponseMessage) message;
            System.out.println("----------------------");
            System.out.println("Group建群消息 : " + msg.getReason());
            System.out.println("----------------------");
        }

        if (message instanceof GroupChatResponseMessage) {
            GroupChatResponseMessage msg = (GroupChatResponseMessage) message;
            System.out.println("----------------------");
            System.out.println(msg.getGroupName() + " 群消息 : " + msg.getContent());
            System.out.println("----------------------");
        }
    }





}
